package org.jeecg.modules.zcgl.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.entity.ApprovalBaseEntity;
import org.jeecg.common.system.base.entity.BaseEntity;
import org.jeecg.common.system.base.entity.DelFlagBaseEntity;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.BigDecimalUtils;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.ReflectHelper;
import org.jeecg.modules.api.enums.TradeStatusEnum;
import org.jeecg.modules.api.utils.ValidatorUtils;
import org.jeecg.modules.api.vo.param.PaymentConfirmationParamVo;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.zcgl.entity.*;
import org.jeecg.modules.zcgl.enums.*;
import org.jeecg.modules.zcgl.mapper.CustomerInfoMapper;
import org.jeecg.modules.zcgl.mapper.LeaseContractInfoMapper;
import org.jeecg.modules.zcgl.mapper.ReceivablesInfoMapper;
import org.jeecg.modules.zcgl.service.*;
import org.jeecg.modules.zcgl.util.NoUtils;
import org.jeecg.modules.zcgl.vo.CollectionInformationVo;
import org.jeecg.modules.zcgl.vo.DemolitionFeeVo;
import org.jeecg.modules.zcgl.vo.ReceivablesInfoVo;
import org.jeecg.modules.zcgl.vo.statistical.BillReceivablesDetailsVo;
import org.jeecg.modules.zcgl.vo.statistical.IncomeOperatingStatisticalVo;
import org.jeecg.modules.zcgl.vo.statistical.PaymentRecordsVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: 应收款项信息
 * @Author: jeecg-boot
 * @Date: 2020-06-23
 * @Version: V1.0
 */
@Service
@Transactional
public class ReceivablesInfoServiceImpl extends ServiceImpl<ReceivablesInfoMapper, ReceivablesInfo> implements IReceivablesInfoService {

    @Resource
    private CustomerInfoMapper customerInfoMapper;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ICustomerBalanceService customerBalanceService;
    @Autowired
    private ICustomerBalanceChangesDetailService iCustomerBalanceChangesDetailService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IReceivablesInfoService iReceivablesInfoService;
    @Resource
    private LeaseContractInfoMapper leaseContractInfoMapper;
    @Autowired
    private ISysBaseAPI iSysBaseAPI;
    @Autowired
    private IOrderDetailsService iOrderDetailsService;
    @Autowired
    private ILeaseContractInfoService iLeaseContractInfoService;


    @Override
    @Transactional
    public boolean demolitionFee(ReceivablesInfoVo vo) {
        this.demolitionFeeCheckModel(vo);
        ReceivablesInfo info = baseMapper.selectById(vo.getId());

        BigDecimal to = BigDecimal.ZERO;
        List<ReceivablesInfo> receivablesInfoList = new ArrayList<>();
        for (int i = 0; i < vo.getDemolitionFeeList().size(); i++) {
            DemolitionFeeVo feel = vo.getDemolitionFeeList().get(i);
            to = to.add(feel.getAmountMoney());
            ReceivablesInfo receivablesInfo = new ReceivablesInfo();
            BeanUtils.copyProperties(info, receivablesInfo, ReflectHelper.getFiledName(ApprovalBaseEntity.class));
            if (i < vo.getDemolitionFeeList().size() - 1) {
                receivablesInfo.setEndTime(DateUtils.nextDay(vo.getDemolitionFeeList().get(i + 1).getStartDate(), -1));
            } else {
                receivablesInfo.setEndTime(info.getEndTime());
            }
            if (i == 0) {
                receivablesInfo.setStartTime(info.getStartTime());
            } else {
                receivablesInfo.setStartTime(feel.getStartDate());
            }
//            receivablesInfo.setAmountConfirmation(YesNoEnum.YES.getStatus());
//            receivablesInfo.setAmountConfirmationTime(DateUtils.getDate());
            receivablesInfo.setRemark(feel.getRemark());
            receivablesInfo.setAmountMoney(feel.getAmountMoney());
            receivablesInfo.setUnAmountMoney(feel.getAmountMoney());
            receivablesInfo.setPaidAmountMoney(BigDecimal.ZERO);
            receivablesInfo.setPayStatus(PayStatusEnum.UNPAID.getStatus());

            receivablesInfo.setOldId(info.getId());
            receivablesInfo.setSysOrgCode(info.getSysOrgCode());
            receivablesInfo.setRentCompanyId(info.getRentCompanyId());
            receivablesInfo.setCompanyId(info.getCompanyId());

            receivablesInfoList.add(receivablesInfo);
        }
        //保存拆费后的数据
        receivablesInfoList.stream().forEach(fee -> {
            baseMapper.insert(fee);
        });
        info.setPayStatus(PayStatusEnum.DEMOLITION_FEE_CANCEL.getStatus());
        baseMapper.updateById(info);
//        //删除原数据
//        baseMapper.deleteById(info.getId());
        return true;
    }

    @Override
    @Transactional
    public boolean toll(ReceivablesInfo vo) {
        ReceivablesInfo receivablesInfo = baseMapper.selectById(vo.getId());
        if (receivablesInfo == null) {
            throw new JeecgBootException("应收款项信息不存在！");
        }
        if (receivablesInfo.getLeaseContractId()==null) {
            throw new JeecgBootException("合同信息不存在！");
        }
        if (receivablesInfo.getPayStatus() != null && receivablesInfo.getPayStatus().intValue() != PayStatusEnum.UNPAID.getStatus()) {
            throw new JeecgBootException("应收款项信息付款状态错误！");
        }
        CustomerInfo customer = customerInfoMapper.selectById(vo.getPaymentBy());
        if (customer == null) {
            throw new JeecgBootException("付款人信息不存在！");
        }
        //判断收款金额和原未收款金额是否相等
        int amount = vo.getPayeeAmount().compareTo(receivablesInfo.getUnAmountMoney());

        String payeeRemark = StringUtils.isBlank(vo.getPayeeRemark()) ? "" : vo.getPayeeRemark();

        //款项说明=预存款
        if(vo.getPaymentInstructions()==25){
            if(amount!=0){
                throw new JeecgBootException("预存款账单收费金额与未收金额不相等！");
            }
            if(vo.getPayType()==60){
                throw new JeecgBootException("预存款账单收费支付方式不能为预存金额！");
            }
        }

        //支付方式=预存金额，收费金额不能大于未收金额
        if(vo.getPayType()==60){
            if(amount>0){
                throw new JeecgBootException("预存金额抵扣收费金额不能大于未收金额！");
            }
        }

        //本次收款后剩余未收
        BigDecimal unMoney = receivablesInfo.getUnAmountMoney().subtract(vo.getPayeeAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);

        CustomerBalance customerBalance = customerBalanceService.selectCustomerIdAndLeaseContractId(receivablesInfo.getLeaseContractId(), customer.getId());
        //支付方式为：余额支付时  预存金额是否充足

        int amount1 = -1;
        //没有余额
        if(customerBalance!=null){
            amount1=customerBalance.getBalance().compareTo(vo.getPayeeAmount());
        }

        //收款金额大于未收金额
        if (amount > 0) {
            BigDecimal amountMoney = vo.getPayeeAmount().subtract(receivablesInfo.getUnAmountMoney()).setScale(2, BigDecimal.ROUND_HALF_UP);
            customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                    customer.getId(), amountMoney, true, receivablesInfo.getId(),
                    HandleTypeEnum.PAY_SURPLUS_RETURN.getStatus(), "线下支付后剩余金额，预存入客户余额",receivablesInfo.getId());
            //修改付款金额为未收款金额
            vo.setPayeeAmount(receivablesInfo.getUnAmountMoney());

        //收款金额小于未收金额
        } else if (amount < 0) {

            //支付方式=预存金额，扣除客户余额
            if(vo.getPayType()==60){

                if(amount1<0){
                    throw new JeecgBootException("预存金额不足！");
                }
                customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                        customer.getId(), vo.getPayeeAmount(), false, receivablesInfo.getId(),
                        HandleTypeEnum.PRESTORE_DEDUCTION.getStatus(), "预存金额支付，扣除客户余额",receivablesInfo.getId());

            }else{

                if (customerBalance != null && customerBalance.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal amountMoney = null;
                    if (unMoney.compareTo(customerBalance.getBalance()) <= 0) {
                        amountMoney = unMoney;
                        //修改付款金额为未收款金额
                        vo.setPayeeAmount(receivablesInfo.getUnAmountMoney());
                    } else {
                        amountMoney = customerBalance.getBalance();
                        //修改付款金额为：当前收款金额+客户余额
                        vo.setPayeeAmount(vo.getPayeeAmount().add(customerBalance.getBalance()).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                    customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                            customer.getId(), amountMoney, false, receivablesInfo.getId(),
                            HandleTypeEnum.PAY_DEDUCTION.getStatus(), "线下支付后不够金额，扣除客户余额",receivablesInfo.getId());

                    payeeRemark = payeeRemark + "【" + DateUtils.date2Str(DateUtils.datetimeFormat.get()) + "客户余额抵扣：" + amountMoney + "】";
                }

            }

        //收款金额=未收金额
        }else {
            //款项说明=预存款
            if(vo.getPaymentInstructions()==25){
                //存客户余额
                customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                        customer.getId(), vo.getPayeeAmount(), true, receivablesInfo.getId(),
                        HandleTypeEnum.DEPOSIT_PAYMENT.getStatus(), "预存款直接存入客户余额",receivablesInfo.getId());
                //修改付款金额为未收款金额
                vo.setPayeeAmount(receivablesInfo.getUnAmountMoney());
            }

            //支付方式=预存金额，扣除客户余额
            if(vo.getPayType()==60){

                if(amount1<0){
                    throw new JeecgBootException("预存金额不足！");
                }
                customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                        customer.getId(), vo.getPayeeAmount(), false, receivablesInfo.getId(),
                        HandleTypeEnum.PRESTORE_DEDUCTION.getStatus(), "预存金额支付，扣除客户余额",receivablesInfo.getId());
            }
        }


        //金额确认
        if (receivablesInfo.getAmountConfirmation() == null || receivablesInfo.getAmountConfirmation().intValue() == YesNoEnum.NO.getStatus()) {
            receivablesInfo.setAmountConfirmation(YesNoEnum.YES.getStatus());
            receivablesInfo.setAmountConfirmationTime(DateUtils.getDate());
        }
        //未收金额=收款金额
        if (receivablesInfo.getUnAmountMoney().compareTo(vo.getPayeeAmount()) == 0) {
            receivablesInfo.setPayStatus(PayStatusEnum.PAID.getStatus());
            receivablesInfo.setPaidAmountMoney(receivablesInfo.getAmountMoney());
            receivablesInfo.setUnAmountMoney(BigDecimal.ZERO);

        //收款金额!=未收金额
        } else {
            receivablesInfo.setPayStatus(PayStatusEnum.UNPAID.getStatus());
            receivablesInfo.setPaidAmountMoney(receivablesInfo.getPaidAmountMoney().add(vo.getPayeeAmount()));
            receivablesInfo.setUnAmountMoney(receivablesInfo.getUnAmountMoney().subtract(vo.getPayeeAmount()));
        }
        List<String> paymentByList = new ArrayList<>();
        if (StringUtils.isNotBlank(receivablesInfo.getPaymentBy())) {
            paymentByList.addAll(Arrays.asList(receivablesInfo.getPaymentBy().split(CommonConstant.DEFAULT_SEPARATOR)));
        }
        if (!paymentByList.contains(vo.getPaymentBy())) {
            paymentByList.add(vo.getPaymentBy());
        }
        receivablesInfo.setPaymentBy(StringUtils.join(paymentByList, CommonConstant.DEFAULT_SEPARATOR));
        receivablesInfo.setPayeeRemark(receivablesInfo.getPayeeRemark() + payeeRemark);
        receivablesInfo.setPayeeRemark(payeeRemark);
        receivablesInfo.setPayType(vo.getPayType());
        receivablesInfo.setReceiptDate(vo.getReceiptDate());
        //判断是否选择收款人，默认当前登录用户
        if (StringUtils.isBlank(vo.getPayeeBy())) {
            LoginUser sysUser = JwtUtil.getLoginUser();
            vo.setPayeeBy(sysUser.getId());
        }
        receivablesInfo.setAttachment(vo.getAttachment());
        receivablesInfo.setPayeeBy(vo.getPayeeBy());

        //检测是否计入欠费信息
        this.checkOwe(receivablesInfo);

        //生成当前扣费的订单详情
        orderService.creatorOrder(vo.getPayeeAmount(), OrderTypeEnum.OFFLINE_PAYMENT.getStatus(), vo.getPaymentBy(), receivablesInfo);

        //未收金额=0
        if (receivablesInfo.getUnAmountMoney() == BigDecimal.ZERO) {
            //查询收费明细赋值
            queryReceivedDetails(receivablesInfo);
        }
        baseMapper.updateById(receivablesInfo);


        return true;
    }

    @Override
    public IPage<ReceivablesInfo> pageByWechat(Page<ReceivablesInfo> page, QueryWrapper<ReceivablesInfo> queryWrapper, Map<String, Object> param) {
        return baseMapper.pageByWechat(page, queryWrapper, param);
    }

    @Override
    public List<String> queryIdList(Wrapper<ReceivablesInfo> queryWrapper, Map<String, Object> param) {
        return baseMapper.queryIdList(queryWrapper, param);
    }

    @Override
    public boolean amountConfirmation(String id, Integer isAllConfirmation) {
        ReceivablesInfo receivablesInfo = baseMapper.selectById(id);
        if (receivablesInfo == null) {
            throw new JeecgBootException("收款信息不存在！");
        }
        if (isAllConfirmation != null && isAllConfirmation.intValue() == 2 && StringUtils.isNotBlank(receivablesInfo.getLeaseContractId())) {
            ReceivablesInfo info = new ReceivablesInfo();
            info.setAmountConfirmation(YesNoEnum.YES.getStatus());
            info.setAmountConfirmationTime(new Date());
            LambdaQueryWrapper<ReceivablesInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ReceivablesInfo::getAmountConfirmation, YesNoEnum.NO.getStatus());
            queryWrapper.eq(ReceivablesInfo::getLeaseContractId, receivablesInfo.getLeaseContractId());
            baseMapper.update(info, queryWrapper);
        } else {
            receivablesInfo.setAmountConfirmation(YesNoEnum.YES.getStatus());
            receivablesInfo.setAmountConfirmationTime(new Date());
            baseMapper.updateById(receivablesInfo);
        }
        return true;
    }

    @Override
    public IPage<CollectionInformationVo> queryCollectionInformationVoList(Page<CollectionInformationVo> page, QueryWrapper<CollectionInformationVo> queryWrapper) {
        return baseMapper.queryCollectionInformationVoList(page, queryWrapper);
    }

    @Override
    public List<CollectionInformationVo> queryCollectionInformationVoList(QueryWrapper<CollectionInformationVo> queryWrapper) {
        return baseMapper.queryCollectionInformationVoList(queryWrapper);
    }

    @Override
    public ReceivablesInfo queryReceivedDetails(ReceivablesInfo receivablesInfos) {

        //获取支付方式（数据字典）
        Map payType=new HashMap();
        List<DictModel> dictModels=iSysBaseAPI.queryDictItemsByCode("pay_type");
        for (DictModel dict: dictModels) {
            payType.put(dict.getValue(),dict.getText());
        }
            //根据已收款项的订单组装收款明细字段

            LambdaQueryWrapper<OrderDetails> lambdaQueryWrapper=new LambdaQueryWrapper();
            String id=receivablesInfos.getId();
            lambdaQueryWrapper.eq(OrderDetails::getReceivablesId,id);

            List<OrderDetails>  orderDetails=iOrderDetailsService.list(lambdaQueryWrapper);

            SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            String payeeDetails="";

            for (OrderDetails order:orderDetails) {
                payeeDetails+="【";
                payeeDetails+="收款时间："+format.format(order.getPayDate())+"  ";
                payeeDetails+="支付方式："+payType.get(order.getPayType()+"")+"  ";
                payeeDetails+="金额："+order.getAmountMoney();
                payeeDetails+="】";
                payeeDetails+="\r";
            }

        receivablesInfos.setPayeeDetails(payeeDetails);

        return receivablesInfos;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean paymentConfirmation(PaymentConfirmationParamVo vo, List<ReceivablesInfo> receivablesInfoList) {
        boolean tradeStatus = TradeStatusEnum.SUCCESS.getKey().equalsIgnoreCase(vo.getTradeStatus());
//        List<PayeeParamVo> payeeList = vo.getPayeeList();
//        Map<String, PayeeParamVo> payeeMap = new HashMap<>();
//        payeeList.forEach(payee -> {
//            payeeMap.put(payee.getRecordedCompanyId(), payee);
//        });
        boolean bool = false;
        //保存支付信息中所有的客户ID
        List<String> customerIds = new ArrayList<>();
        List<OrderDetails> orderDetailsList = new ArrayList<>();
        //循环收款信息
        receivablesInfoList.stream().forEach(receivablesInfo -> {

            List<String> customerIdList = new ArrayList<>();
            if (StringUtils.isNotBlank(receivablesInfo.getCustomerId())) {
                customerIdList = Arrays.asList(receivablesInfo.getCustomerId().split(CommonConstant.DEFAULT_SEPARATOR));
                //遍历当前支付款项的客户ID，如果不包含在列表里面就加入到列表
                for (String id : customerIdList) {
                    if (!customerIds.contains(id)) {
                        customerIds.add(id);
                    }
                }
            }

            if (tradeStatus) {

                //如果计入欠费信息后，查询用户信息更新用户欠费信息
                this.checkOwe(receivablesInfo);

                //修改资产付款信息和状态
                receivablesInfo.setPaidAmountMoney(receivablesInfo.getAmountMoney());
                receivablesInfo.setUnAmountMoney(BigDecimal.ZERO);
                receivablesInfo.setPayStartDate(DateUtils.getDate());
                receivablesInfo.setPayStatus(PayStatusEnum.PAID.getStatus());
                receivablesInfo.setPayType(PayTypeEnum.CCQTGB.getStatus());
                receivablesInfo.setPaymentSlipNumber(vo.getTransactionId());
                receivablesInfo.setPaymentBy(vo.getCustomerId());
                receivablesInfo.setPayeeBy("-1");
                boolean bool1 = super.retBool(baseMapper.updateById(receivablesInfo));
                this.checkBool(bool1);
            }

            //生成订单详情
            OrderDetails orderDetails = new OrderDetails();
            BeanUtils.copyProperties(receivablesInfo, orderDetails, ReflectHelper.getFiledName(DelFlagBaseEntity.class));
//            orderDetails.setAmountMoney(receivablesInfo.getAmountMoney());
//            orderDetails.setLeaseContractId(receivablesInfo.getLeaseContractId());
//            orderDetails.setAssetId(receivablesInfo.getAssetId());
//            orderDetails.setAssetSubIds(receivablesInfo.getAssetSubIds());
//            orderDetails.setCustomerId(receivablesInfo.getCustomerId());
//            orderDetails.setEndTime(receivablesInfo.getEndTime());
//            orderDetails.setStartTime(receivablesInfo.getStartTime());
//            orderDetails.setReceivablesId(receivablesInfo.getId());
//            orderDetails.setPaymentInstructions(receivablesInfo.getPaymentInstructions());
//            orderDetails.setCompanyId(receivablesInfo.getCompanyId());
//            orderDetails.setRentCompanyId(receivablesInfo.getRentCompanyId());
//            orderDetails.setSysOrgCode(receivablesInfo.getSysOrgCode());

            orderDetails.setPayStatus(tradeStatus ? AttentionPayStatusEnum.SUCCESSFUL.getStatus() : AttentionPayStatusEnum.FAILED.getStatus());
            orderDetails.setPayType(PayTypeEnum.CCQTGB.getStatus());
            orderDetails.setOrderType(OrderTypeEnum.INITIATIVE_PAY.getStatus());
            orderDetails.setPayeeName(vo.getPayeeName());
            orderDetails.setPayeeAccount(vo.getPayeeAccount());
            orderDetails.setPayeeBankDeposit(vo.getPayeeBankDeposit());
            orderDetails.setReceivablesId(receivablesInfo.getId());
            orderDetails.setPayDate(DateUtils.str2Date(vo.getTradeTime(), DateUtils.datetimeFormat.get()));


            orderDetailsList.add(orderDetails);

        });

        //生成订单信息
        Order order = new Order();
        BeanUtils.copyProperties(vo, order, "amountMoney", "tradeTime");
        order.setPayStatus(tradeStatus ? AttentionPayStatusEnum.SUCCESSFUL.getStatus() : AttentionPayStatusEnum.FAILED.getStatus());
        order.setAmountMoney(new BigDecimal(vo.getAmountMoney() / 100.0).setScale(2, BigDecimal.ROUND_HALF_UP));
//        order.setCustomerId(StringUtils.join(customerIds, ","));
        order.setCustomerId(vo.getCustomerId());
        order.setOrderNo(NoUtils.getOrderNo());
        order.setOrderType(OrderTypeEnum.INITIATIVE_PAY.getStatus());
        order.setCompanyId(receivablesInfoList.get(0).getCompanyId());
        order.setSysOrgCode(receivablesInfoList.get(0).getSysOrgCode());
        order.setRentCompanyId(vo.getRecordedCompanyId());
        order.setTradeTime(DateUtils.str2Date(vo.getTradeTime(), DateUtils.datetimeFormat.get()));
        //保存订单和订单详情
        bool = orderService.saveMain(order, orderDetailsList);
        this.checkBool(bool);
        return true;
    }

    @Override
    public boolean nullify(ReceivablesInfo vo) {

        int status=vo.getIsNullify()==null?0:vo.getIsNullify();
        if(status==1){
            throw new JeecgBootException("该账单已作废！");
        }

        //新增相同的应收账单
        ReceivablesInfo receivablesInfo=new ReceivablesInfo();
        BeanUtils.copyProperties(vo,receivablesInfo);
        receivablesInfo.setId(null);
        receivablesInfo.setUnAmountMoney(vo.getAmountMoney());
        receivablesInfo.setPaidAmountMoney(BigDecimal.ZERO);
        receivablesInfo.setAmountConfirmation(0);
        receivablesInfo.setAmountConfirmationTime(null);
        receivablesInfo.setPayStatus(10);
        receivablesInfo.setPayType(null);
        receivablesInfo.setReceiptDate(null);
        receivablesInfo.setPayeeBy(null);
        receivablesInfo.setPayeeRemark(null);
        receivablesInfo.setPaymentSlipNumber(null);
        receivablesInfo.setPaymentBy(null);
        receivablesInfo.setCreateTime(new Date());
        receivablesInfo.setUpdateBy(null);
        receivablesInfo.setUpdateTime(null);
        receivablesInfo.setRemark(null);
        receivablesInfo.setVersionFlag(1);
        receivablesInfo.setPayeeDetails(null);

        iReceivablesInfoService.save(receivablesInfo);

        //判断收费时存在预存金额存入或者抵扣进行恢复
        checkCustomerBalance(vo);

        //作废
        vo.setIsNullify(1);
        iReceivablesInfoService.saveOrUpdate(vo);
        return true;
    }

    /**
     * 检查该账单收款时是否多收存入客户余额或者使用预存金额抵扣
     * @param receivablesInfo
     */
    public void checkCustomerBalance(ReceivablesInfo receivablesInfo){

        LambdaQueryWrapper<CustomerBalanceChangesDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerBalanceChangesDetail::getReceivablesId,receivablesInfo.getId());

        List<CustomerBalanceChangesDetail> list= iCustomerBalanceChangesDetailService.list(queryWrapper);

        for (CustomerBalanceChangesDetail customerBalanceChangesDetail: list) {
                //收费时增加多少预存对应减少多少;收费时预存抵扣了多少对应增加多少
                if(customerBalanceChangesDetail.getChangesType()==1){
                    //余额变更
                    boolean bool = customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                            receivablesInfo.getCustomerId(), customerBalanceChangesDetail.getChangesAmount(), false, receivablesInfo.getId(),
                            HandleTypeEnum.DELETE_RETURN.getStatus(), "作废已收恢复预存金额",receivablesInfo.getId());
                    //生成当前缴费的订单详情
                    boolean orderbool = orderService.creatorOrder(customerBalanceChangesDetail.getChangesAmount(), OrderTypeEnum.OFFLINE_PAYMENT.getStatus(), receivablesInfo.getCustomerId(), receivablesInfo);

                    if(bool==false||orderbool==false){
                        throw new JeecgBootException("客户预存金额异常！");
                    }

                }else{

                    //余额变更
                    boolean bool = customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                            receivablesInfo.getCustomerId(), customerBalanceChangesDetail.getChangesAmount(), true, receivablesInfo.getId(),
                            HandleTypeEnum.DELETE_ADD.getStatus(), "作废已收恢复预存抵扣",receivablesInfo.getId());
                    //生成当前扣费的订单详情
                    boolean orderbool = orderService.creatorOrder(customerBalanceChangesDetail.getChangesAmount(), OrderTypeEnum.OFFLINE_PAYMENT.getStatus(), receivablesInfo.getCustomerId(), receivablesInfo);

                    if(bool==false||orderbool==false){
                        throw new JeecgBootException("客户预存金额异常！");
                    }

                }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean paymentConfirmation(PaymentConfirmationParamVo vo) {

        String validateResult = ValidatorUtils.validateFastStr(vo);
        if (validateResult != null) {
            throw new JeecgBootException(validateResult);
        }
        if (vo.getOrderIds().size() == 0) {
            throw new JeecgBootException("待付款信息ID不能为空！");
        }

        //查询支付订单号是否已存在，如果存在表示已处理过，直接返回
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        Order order = new Order();
        order.setTransactionId(vo.getTransactionId());
        queryWrapper.setEntity(order);
        Integer num = orderService.count(queryWrapper);
        if (num != null && num > 0) {
            return true;
        }

        String companyId = sysDepartService.selectCompanyIdByName(vo.getRecordedCompanyName());
        if (StringUtils.isBlank(companyId)) {
            throw new JeecgBootException("入账公司不存在，支付处理失败！");
        }
        vo.setRecordedCompanyId(companyId);

        //缴费的应收款项列表
        List<ReceivablesInfo> receivablesInfoList = new ArrayList<>();
        //存储总付款金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        //存储入账公司对应的应付款总额
        Map<String, BigDecimal> companyTotalAmountMap = new HashMap<>();
        for (String id : vo.getOrderIds()) {
            ReceivablesInfo receivablesInfo = this.getById(id);
            if (receivablesInfo == null || (receivablesInfo.getPayStatus() != null && PayStatusEnum.UNPAID.getStatus() != receivablesInfo.getPayStatus().intValue())) {
                throw new JeecgBootException("有付款信息不存在或已支付，支付失败！");
            }
            if (!receivablesInfo.getRentCompanyId().equalsIgnoreCase(companyId)) {
                throw new JeecgBootException("有入账单位不一致，支付处理失败！");
            }
            totalAmount = totalAmount.add(receivablesInfo.getUnAmountMoney());
            receivablesInfoList.add(receivablesInfo);
            BigDecimal companyTotalAmount = companyTotalAmountMap.get(receivablesInfo.getRentCompanyId());
            if (companyTotalAmount == null) {
                companyTotalAmount = receivablesInfo.getUnAmountMoney();
            } else {
                companyTotalAmount = companyTotalAmount.add(receivablesInfo.getUnAmountMoney());
            }
            companyTotalAmountMap.put(receivablesInfo.getRentCompanyId(), companyTotalAmount);
        }

        //根据收款信息统计的金额和支付的总金额对比，如果不相等表示支付金额错误，直接返回失败
        if (totalAmount.compareTo(new BigDecimal(vo.getAmountMoney() / 100.0).setScale(2, BigDecimal.ROUND_HALF_UP)) != 0) {
            throw new JeecgBootException("款项总金额不一致，支付处理失败！");
        }
        return this.paymentConfirmation(vo, receivablesInfoList);
    }


    @Override
    public void checkModel(ReceivablesInfo receivablesInfo) {
        if (StringUtils.isNotBlank(receivablesInfo.getLeaseContractId())) {
            LeaseContractInfo leaseContractInfo = leaseContractInfoMapper.selectById(receivablesInfo.getLeaseContractId());
            if (leaseContractInfo != null) {
                receivablesInfo.setAssetId(leaseContractInfo.getAssetId());
                receivablesInfo.setAssetSubIds(leaseContractInfo.getAssetSubIds());
                receivablesInfo.setCustomerId(leaseContractInfo.getCustomerId());
            } else {
                throw new JeecgBootException("合同信息不存在");
            }
        } else {
            if (StringUtils.isBlank(receivablesInfo.getCustomerId())) {
                throw new JeecgBootException("请填写客户信息");
            }
            CustomerInfo customerInfo = customerInfoMapper.selectById(receivablesInfo.getCustomerId());
            if (customerInfo == null) {
                throw new JeecgBootException("客户信息不存在");
            }
        }
        if (StringUtils.isNotBlank(receivablesInfo.getId())) {
            ReceivablesInfo info = baseMapper.selectById(receivablesInfo.getId());
            if (info == null) {
                throw new JeecgBootException("收款信息不存在！");
            }
            if ((info.getPaidAmountMoney() != null
                    && info.getPaidAmountMoney().compareTo(BigDecimal.ZERO) != 0)
                    || info.getAmountMoney().compareTo(info.getUnAmountMoney()) != 0) {
                throw new JeecgBootException("款项已收过款，不能修改！");
            }
        }
        if (receivablesInfo.getEndTime() != null && receivablesInfo.getStartTime() != null) {
            if (DateUtils.sameDate(receivablesInfo.getEndTime(), receivablesInfo.getStartTime()) == -1) {
                throw new JeecgBootException("结束日期必须在开始日期之后");
            }
        }
        if (receivablesInfo.getPayStatus() == null) {
            receivablesInfo.setPayStatus(PayStatusEnum.UNPAID.getStatus());
        }
        if (receivablesInfo.getAmountConfirmation() == null) {
            receivablesInfo.setAmountConfirmation(YesNoEnum.NO.getStatus());
        }
        if (receivablesInfo.getPayStartDate() == null) {
            receivablesInfo.setPayStartDate(new Date());
        }
    }

    @Override
    public void demolitionFeeCheckModel(ReceivablesInfoVo vo) {

        ReceivablesInfo info = baseMapper.selectById(vo.getId());
        if (info == null) {
            throw new JeecgBootException("应收款项信息不存在");
        }
        if ((info.getPaidAmountMoney() != null
                && info.getPaidAmountMoney().compareTo(BigDecimal.ZERO) != 0)
                || info.getAmountMoney().compareTo(info.getUnAmountMoney()) != 0) {
            throw new JeecgBootException("款项已收过款，不能拆费！");
        }

        BigDecimal to = BigDecimal.ZERO;
        if (vo.getDemolitionFeeList() == null || vo.getDemolitionFeeList().size() <= 1) {
            throw new JeecgBootException("拆费详情不能为空或者一条");
        }
        Collections.sort(vo.getDemolitionFeeList(), new Comparator<DemolitionFeeVo>() {
            public int compare(DemolitionFeeVo o1, DemolitionFeeVo o2) {
                if (o1.getStartDate() == null || o2.getStartDate() == null) {
                    throw new JeecgBootException("拆费详情开始日期不能为空");
                }
                return o1.getStartDate().compareTo(o2.getStartDate());
            }
        });
        for (int i = 0; i < vo.getDemolitionFeeList().size(); i++) {
            DemolitionFeeVo feel = vo.getDemolitionFeeList().get(i);
            if (info.getStartTime().after(feel.getStartDate()) || feel.getStartDate().after(info.getEndTime())) {
                throw new JeecgBootException("拆费的日期必须在原开始日期和结束日期之间");
            }
            if (feel.getAmountMoney() == null || feel.getAmountMoney().compareTo(BigDecimal.ZERO) <= 0) {
                throw new JeecgBootException("拆费的金额必须大于0");
            }
            to = to.add(feel.getAmountMoney());
        }
        if (to.subtract(info.getAmountMoney()).abs().compareTo(new BigDecimal(0.02)) > 0) {
            throw new JeecgBootException("拆费后的总费用必须和原费用相等");
        }
    }

    @Override
    public IPage<PaymentRecordsVo> queryPaymentRecordsList(Page<PaymentRecordsVo> page, QueryWrapper<PaymentRecordsVo> queryWrapper) {
        return baseMapper.queryPaymentRecordsList(page,queryWrapper);
    }

    @Override
    public List<PaymentRecordsVo> queryPaymentRecordsList(QueryWrapper<PaymentRecordsVo> queryWrapper) {
        return baseMapper.queryPaymentRecordsList(queryWrapper);
    }

    @Override
    public IPage<BillReceivablesDetailsVo> queryBillReceivablesDetailsPageList(Page<BillReceivablesDetailsVo> page, QueryWrapper<BillReceivablesDetailsVo> queryWrapper) {
        return baseMapper.queryBillReceivablesDetailsPageList(page,queryWrapper);
    }

    @Override
    public List<BillReceivablesDetailsVo> queryBillReceivablesDetailsList(QueryWrapper<BillReceivablesDetailsVo> queryWrapper) {
        return baseMapper.queryBillReceivablesDetailsPageList(queryWrapper);
    }

    @Override
    public IPage<IncomeOperatingStatisticalVo> queryIncomeOperatingStatisticalPageList(Page<IncomeOperatingStatisticalVo> page, QueryWrapper<IncomeOperatingStatisticalVo> queryWrapper) {
        return baseMapper.queryIncomeOperatingStatisticalPageList(page,queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void automaticDeduction(ReceivablesInfo receivablesInfo) {
        //如果付款状态为空，设置为未付款
        if (receivablesInfo.getPayStatus() == null) {
            receivablesInfo.setPayStatus(PayStatusEnum.UNPAID.getStatus());
        }
        //设置为未计入欠费
        if (receivablesInfo.getIzOwe() == null) {
            receivablesInfo.setIzOwe(YesNoEnum.NO.getStatus());
        }
        //设置为未确认
        if (receivablesInfo.getAmountConfirmation() == null) {
            receivablesInfo.setAmountConfirmation(YesNoEnum.NO.getStatus());
            return;
        }
        if (StringUtils.isBlank(receivablesInfo.getCustomerId())) {
            return;
        }
        receivablesInfo.setPayeeRemark("自动扣费");
        receivablesInfo.setPayType(60);//预存支付
        receivablesInfo.setReceiptDate(DateUtils.getDate());

        //应收款项的客户IDS
        String[] customerIds = receivablesInfo.getCustomerId().split(CommonConstant.DEFAULT_SEPARATOR);
        //查询客户在合同的余额列表
        LambdaQueryWrapper<CustomerBalance> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CustomerBalance::getLeaseContractId, receivablesInfo.getLeaseContractId());
        wrapper.in(CustomerBalance::getCustomerId, customerIds);
        List<CustomerBalance> customerBalances = customerBalanceService.list(wrapper);

        //未收款金额
        BigDecimal un = receivablesInfo.getUnAmountMoney();
        //付款的客户IDS
        List<String> pidCustomerIds = new ArrayList<>();
        if (StringUtils.isNotBlank(receivablesInfo.getPayeeBy())) {
            pidCustomerIds.addAll(Arrays.asList(receivablesInfo.getPayeeBy().split(CommonConstant.DEFAULT_SEPARATOR)));
        }

        boolean bool = false;
        if (customerBalances != null && customerBalances.size() > 0) {
            //记录每次付款金额
            BigDecimal pid = BigDecimal.ZERO;
            for (CustomerBalance balance : customerBalances) {
                if (balance.getBalance().compareTo(un) >= 0) {
                    balance.setBalance(balance.getBalance().subtract(un));
                    pid = un;
                    un = BigDecimal.ZERO;
                } else if (balance.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                    un = un.subtract(balance.getBalance());
                    pid = balance.getBalance();
                    balance.setBalance(BigDecimal.ZERO);
                } else {
                    continue;
                }
                //余额变更
                bool = customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                        balance.getCustomerId(), pid, false, receivablesInfo.getId(),
                        HandleTypeEnum.RENTAL_FEE.getStatus(), "自动扣费！",receivablesInfo.getId());
                this.checkBool(bool);
                //生成当前扣费的订单详情
                bool = orderService.creatorOrder(pid, OrderTypeEnum.AUTOMATIC_DEDUCTION.getStatus(), balance.getCustomerId(), receivablesInfo);
                this.checkBool(bool);
                if (!pidCustomerIds.contains(balance.getCustomerId())) {
                    pidCustomerIds.add(balance.getCustomerId());
                }
                if (un.compareTo(BigDecimal.ZERO) == 0) {
                    break;
                }
            }
        }

        receivablesInfo.setPaymentBy(StringUtils.join(pidCustomerIds, CommonConstant.DEFAULT_SEPARATOR));

        BigDecimal pid = receivablesInfo.getUnAmountMoney().subtract(un);
        if (un.compareTo(BigDecimal.ZERO) > 0) {

            receivablesInfo.setPayStatus(PayStatusEnum.UNPAID.getStatus());

            if (pid.compareTo(BigDecimal.ZERO) > 0) {
                receivablesInfo.setPaidAmountMoney(receivablesInfo.getPaidAmountMoney().add(pid));
                receivablesInfo.setUnAmountMoney(un);
            } else {
                receivablesInfo.setPayeeRemark("");
            }
        } else {
            receivablesInfo.setPayStatus(PayStatusEnum.PAID.getStatus());
            receivablesInfo.setPaidAmountMoney(receivablesInfo.getAmountMoney());
            receivablesInfo.setUnAmountMoney(BigDecimal.ZERO);
            receivablesInfo.setPayeeBy("-1");
        }
        //未收金额=0
        if (un == BigDecimal.ZERO) {
            //查询收费明细赋值
            queryReceivedDetails(receivablesInfo);
        }
        bool = super.updateById(receivablesInfo);
        this.checkBool(bool);
    }

    @Override
    public void saveOrUpdateById(ReceivablesInfo receivablesInfo) {
        this.checkModel(receivablesInfo);
        receivablesInfo.setUnAmountMoney(receivablesInfo.getAmountMoney());
        receivablesInfo.setPaidAmountMoney(BigDecimal.ZERO);
        //新增账单关联合同时，入账公司null，则取合同出租方
        if(receivablesInfo.getLeaseContractId()!=null&&receivablesInfo.getRentCompanyId()==null){
            LeaseContractInfo leaseContractInfo= iLeaseContractInfoService.getById(receivablesInfo.getLeaseContractId());
            receivablesInfo.setRentCompanyId(leaseContractInfo.getRentCompanyId());
        }
        super.saveOrUpdate(receivablesInfo);

    }

    /**
     * 检测是否计入欠费信息，查询用户信息更新用户欠费信息
     *
     * @param receivablesInfo
     */
    private void checkOwe(ReceivablesInfo receivablesInfo) {
        List<String> customerIds = new ArrayList<>();
        if (StringUtils.isNotBlank(receivablesInfo.getCustomerId())) {
            List<String> customerIdList = Arrays.asList(receivablesInfo.getCustomerId().split(CommonConstant.DEFAULT_SEPARATOR));
            //遍历当前支付款项的客户ID，如果不包含在列表里面就加入到列表
            for (String id : customerIdList) {
                if (!customerIds.contains(id)) {
                    customerIds.add(id);
                }
            }
        }
        if (receivablesInfo.getIzOwe() != null && YesNoEnum.YES.getStatus() == receivablesInfo.getIzOwe().intValue()) {
            customerIds.forEach(id -> {
                boolean bool = customerBalanceService.updateBalanceByCustomerIdAndLeaseContractId(receivablesInfo.getRentCompanyId(),receivablesInfo.getLeaseContractId(),
                        id, receivablesInfo.getUnAmountMoney(), true, receivablesInfo.getId(),
                        HandleTypeEnum.PAY_COST_RETURN.getStatus(),
                        "计入欠费后，选择缴费退回计入的欠费金额：" + BigDecimalUtils.formatToThousands(receivablesInfo.getUnAmountMoney()),receivablesInfo.getId());
                this.checkBool(bool);
            });
        }
    }

    private void checkBool(boolean bool) {
        if (!bool) {
            throw new JeecgBootException("错误");
        }
    }
}
